% Authors: Francisco Pinto & Bruno Maia
% Date: 22-09-2011
%
% This file is part of "Breakthrough"

% General utilities

% list_length/2
% Modes: (+,?)
% True if List is a list of size Length
list_length([], 0).

list_length([_ | Tail], Length) :-
  list_length(Tail, TailLength),
  Length is TailLength + 1.

% generate_list/2
% Modes: (+,+,-), (-,-,+)
% Generates a list comprised of NElements Element
generate_list(Element, NElements, [Element|Result]) :-
  NElements > 0,
  NewNElements is NElements - 1,
  generate_list(Element, NewNElements, Result).
  
generate_list(_, 0, []).

% get_element/3
% Modes: (+,+,?)
% True if List is a list of size Length
get_element([Head|_], 0, Head).
  
get_element([_|Tail], Index, Element) :-
  Index \= 0,
  NewIndex is Index - 1,
  get_element(Tail, NewIndex, Element).

% contains/2
% Modes: (+,?)
% True if List contains Element
contains([Head|_], Head). 

contains([Head|Tail], Element) :-
  Element \= Head,
  contains(Element, Tail).

% reverse/2
% Modes: (+,?), (?,+)
% True if Inv is List, reversed
reverse([], []).

reverse([Head|Tail], Inv) :-
  reverse(Tail, Aux),
  concatenate(Aux, [Head], Inv).

% append/3
% Modes: (?,?,?)
% True if the third parameter is the concatenation of the first two, in order
concatenate([], List, List).

concatenate([Head|Tail1], List, [Head|Tail2]) :-
  concatenate(Tail1, List, Tail2).

% set_element_at_index/4
% Modes: (+,?,?,?)
% True if Result is List with its Index-nth element replaced by Element
set_element_at_index([Head|Tail], Index, Element, Result) :-
  Index > 0,
  NewIndex is Index - 1,
  set_element_at_index(Tail, NewIndex, Element, NewList),
  concatenate([Head], NewList, Result).
  
set_element_at_index([_|Tail], 0, Element, Result) :-
  concatenate([Element], Tail, Result).
